package com.ljl.ningwei.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ljl.ningwei.dto.MaterialListByJoinDTO;
import com.ljl.ningwei.entity.Category;
import com.ljl.ningwei.entity.Material;
import com.ljl.ningwei.common.event.CategoryDeletedEvent;
import com.ljl.ningwei.mapper.MaterialMapper;
import com.ljl.ningwei.common.page.PageInfoByApp;
import com.ljl.ningwei.common.page.PageInfoByPC;
import com.ljl.ningwei.service.CategoryService;
import com.ljl.ningwei.service.MaterialService;
import com.ljl.ningwei.common.utils.TimeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Optional;

/**
 * MaterialService 接口
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MaterialServiceImpl implements MaterialService {
    private final MaterialMapper materialMapper;
    private final CategoryService categoryService;
    private final ObjectMapper jsonMapper;

    @Override
    public Material getById(Long id) {
        return Optional.ofNullable(materialMapper.getById(id))
                .orElseThrow(() -> new RuntimeException("查询物料 id " + id + " 结果为空"));
    }

    @Override
    public Material extractById(Long id) {
        return Optional.ofNullable(materialMapper.extractById(id))
                .orElseThrow(() -> new RuntimeException("查询物料结果为空"));
    }

    @Override
    public Long edit(Long id, String name, Long categoryId, String productName, Integer materialCount, String imageUrls) {
        // 检查分类是否存在
        // 优先检查分类
        if (ObjectUtils.isNotEmpty(categoryId)) {
            Category category = categoryService.getById(categoryId);
            if (category == null) {
                throw new RuntimeException("分类" + categoryId + " 不存在，编辑失败");
            }
        }


        if (id == null) {
            // 插入添加校验
            insertValied(name, categoryId, productName, materialCount, imageUrls);
        } else {
            // 更新操作前，先查询物料是否存在
            if (materialMapper.extractById(id) == null) {
                throw new RuntimeException("物料" + id + " 不存在，更新失败");
            }
        }
        // 对象转化
        Material material = toDTO(id, name, categoryId, productName, materialCount, imageUrls);
        int result = id == null ? materialMapper.insert(material) : materialMapper.update(material);
        if (result == 0) {
            throw new RuntimeException("物料编辑失败");
        }
        return material.getId();
    }

    private Material toDTO(Long id, String name, Long categoryId, String productName, Integer materialCount, String imageUrls) {
        return Material.builder()
                .id(id)
                .name(name)
                .categoryId(categoryId)
                .productName(productName)
                .materialCount(materialCount)
                .imageUrls(imageUrls)
                .createTime(id == null ? TimeUtil.getTime() : null)
                .updateTime(TimeUtil.getTime())
                .build();
    }

    private void insertValied(String name, Long categoryId, String productName, Integer materialCount, String imageUrls) {
        //前置校验进行检查
        // 校验名称
        if (StringUtils.isBlank(name)) {
            throw new RuntimeException("名称不能为空");
        }
        // 校验分类名称
        if (ObjectUtils.isEmpty(categoryId)) {
            throw new RuntimeException("分类Id不能为空");
        }
        // 校验产品名称
        if (StringUtils.isBlank(productName)) {
            throw new RuntimeException("产品名称不能为空");
        }
        // 校验物料数量
        if (ObjectUtils.isEmpty(materialCount) || materialCount < 0) {
            throw new RuntimeException("物料数量不能为空或小于0");
        }
        // 校验产品名称
        if (StringUtils.isBlank(imageUrls)) {
            throw new RuntimeException("图片路径不能为空");
        }
    }

    @Override
    public PageInfoByPC getMaterialListByPc(Integer pageNum, Integer pageSize, String keyword) {
        // 检查参数
        pageValied(pageNum, pageSize);
        Integer startIndex = (pageNum - 1) * pageSize;
        int total = materialMapper.count();
        // 检查分页参数是否超出数据范围
        if (startIndex >= total) {
            // 如果起始索引超出总记录数，返回空列表
            return new PageInfoByPC<>(pageNum, pageSize, total);
        }
        // 如果起始索引 + 每页大小超出总记录数，调整每页大小
        if (startIndex + pageSize > total) {
            pageSize = total - startIndex;
        }
        // 获取物料详情
        List<Material> materialList = materialMapper.getList(startIndex, pageSize, keyword, null);

        if (CollectionUtils.isEmpty(materialList)) {
            throw new RuntimeException("分页物料查询结果为异常为空");
        }
        return PageInfoByPC.of(pageNum, pageSize, total, materialList);
    }

    private void pageValied(Integer pageNum, Integer pageSize) {
        if (pageNum <= 0 || pageSize <= 0) {
            throw new RuntimeException("分页结果查询为空");
        }
    }

    @Override
    public PageInfoByApp getMaterialListByApp(Integer pageNum, Integer pageSize, String keyword) throws JsonProcessingException {
        // 开始索引
        Integer startIndex = (pageNum - 1) * pageSize;
        // 看看有没有子sql
        String categoryIds = null;
        if (StringUtils.isNotBlank(keyword)) {
            List<Long> ids = categoryService.getIdsByName(keyword);
            categoryIds = StringUtils.join(ids, ",");
        }
        List<Material> materialList = materialMapper.getList(startIndex, pageSize + 1, keyword, categoryIds);
        // 是否结束
        Boolean isEnd = materialList.isEmpty() || materialList.size() <= pageSize;
        // 没有结束就截取掉最后一条记录
        if (!isEnd) materialList.remove(materialList.size() - 1);
        // 生成json字符串
        return PageInfoByApp.of(isEnd, materialList);
    }

    @Override
    public PageInfoByApp<Material> getMaterialListByAppAndCid(Integer pageNum, Integer pageSize, Integer cid) {
        // 开始索引
        Integer startIndex = (pageNum - 1) * pageSize;
        // 看看有没有子sql
        String categoryIds = cid.toString();
        List<Material> materialList = materialMapper.getList(startIndex, pageSize + 1, null, categoryIds);
        // 是否结束
        Boolean isEnd = materialList.isEmpty() || materialList.size() <= pageSize;
        // 没有结束就截取掉最后一条记录
        if (!isEnd) materialList.remove(materialList.size() - 1);
        // 生成json字符串
        return PageInfoByApp.of(isEnd, materialList);
    }




    @Override
    public PageInfoByPC<MaterialListByJoinDTO> getMaterialListByJoinDTO(Integer pageNum, Integer pageSize, String keyword) {
        // 检查参数
        pageValied(pageNum, pageSize);
        Integer startIndex = (pageNum - 1) * pageSize;
        int total = materialMapper.count();
        // 检查分页参数是否超出数据范围
        if (startIndex >= total) {
            // 如果起始索引超出总记录数，返回空列表
            return new PageInfoByPC<>(pageNum, pageSize, total);
        }
        // 如果起始索引 + 每页大小超出总记录数，调整每页大小
        if (startIndex + pageSize > total) {
            pageSize = total - startIndex;
        }
        // 获取物料详情
        List<MaterialListByJoinDTO> materialList = materialMapper.getListByJoin(startIndex, pageSize, keyword, null);

        if (CollectionUtils.isEmpty(materialList)) {
            throw new RuntimeException("分页物料查询结果为异常为空");
        }
        return PageInfoByPC.of(pageNum, pageSize, total, materialList);
    }



    @EventListener
    public void handleCategoryDeletedEvent(CategoryDeletedEvent event) {
        Long categoryId = event.getCategoryId();
        // 执行删除关联商品的操作
        log.info("关联的商品被删除");
        materialMapper.deleteByCategoryId(categoryId);
        // 该关联的商品也已经被删除了
    }


    @Override
    public void delete(Long id) {
        // 插入操作并直接返回布尔值
        if (materialMapper.delete(id) == 0) {
            throw new RuntimeException("物料" + id + "删除异常");
        }
    }
}
